package ua.tach.shortl.logic;

import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

public class CityPlace extends Link{
	public static final float SINGLEANGLE = 90f/(Rail.BASERAILSIZE*1.6f);
	public static final float TORADIAN = 3.1416f/180f;
	public static final int TIMETOLOAD = 10;

	// for rail selector
	// first 4 - left city, next 4 - right city
	private final static int[] NEXT_ENDX  = {
		0, -1, -1, -1, 1, 0, 1, 1
	};
	private final static int[] NEXT_ENDY  = {
		1, 0, 1, 1, 0, -1, -1, -1
	};
	private final static int[] NEXT_ENDDIR  = { // !!! only if start==0
		3, 0, 0, 3, 2, 1, 1, 2
	};
	private final static float[] NEXT_ENDROT  = {
		90f, 0, 180f, 0, 0, 90f, 180f, 0
	};

	public int color ;
	public Rail station = Rail.NULL;
	private Switch depot = new Depot(this, 0);
	private RailPosition newTrainPosition;
	private int housesLeft;

	// Train standing on station until rail freed
	public Train waitingTrain = Train.NULL;
	public int waitingCounter;
	public int railBusy;

	public CityPlace (Point ind) {
		super(ind);
		housesLeft = 0;
		color = 6; // City without color yet
	}

	public boolean isFree(int dir) {
		return false;
	}

	public void render(GL10 gl) {
		if (waitingTrain == Train.NULL) return;
	}

	public Rail getNext(int dir) {
		return station;
	}

	public void trainTick() {
		if (waitingTrain != Train.NULL) {
			if (waitingCounter == 0) {
				if (railBusy == 0) {
					System.out.println(" Add train to line ");
					Country.addTrain(waitingTrain);
					waitingTrain = Train.NULL;
				} else {
					System.out.println("Waiting train penalty, rb= "+ railBusy);
					waitingCounter = TIMETOLOAD;
				}
			} else --waitingCounter;
		}
	}

	public void tick() {
		if (housesLeft == 0) return;
		if (--housesLeft == 0) {
			buildCity();
		} else {
			// put new house
			Vector2 p = new Vector2(index.x, index.y);
			if (p.x > p.y) 
				p.add(-0.5f, 0.5f);
			else
				p.add(0.5f, -0.5f);
			while (true) {
				if ( Country.checkTree( p.add(Country.randomGenerator.nextFloat()*0.5f-0.25f,Country.randomGenerator.nextFloat()*0.5f-0.25f))) continue;
				Country.trees.add(new Tree (p, 2, Country.randomGenerator.nextFloat()*90 + 45 , Country.CITY_COLORS[color]));
				return;
			}
		}
	}

	public void startTrain () {
		System.out.println("Start at "+ index);
		if (waitingTrain == Train.NULL) {
			waitingTrain = new Train(color, newTrainPosition, 0.35f);
			waitingCounter = TIMETOLOAD;
			waitingTrain.waiting = true;
		}
	}

	public void startCity ( int col ) {
		color = col;
		housesLeft = 15;
	}

	public void buildCity() {
		newTrainPosition = new RailPosition();
		station = new CityRail();
		station.connectTo(index);
		newTrainPosition.base = station;

		// Register new city in country
		Country.addSwitch(depot);
		Country.addRail(station);
	}

	private class Depot extends Switch {

		public Depot(Link p, int d) {
			super(p, d);
		}

		public boolean click() {
			System.out.println("Click on city");
			if (waitingTrain != Train.NULL)
				waitingTrain.dispose();
			waitingTrain = new Drezina(color, newTrainPosition, 0);
			waitingCounter = 1;
			return true;
		}

        public boolean isFree() {
        	return true;
        }

		@Override
		public void render(GL10 gl) {
		}

		public int getRailCount() {
			return 0;
		}

		public Rail getRail () {
			return Rail.NULL;
		}

		public boolean checkRail() {
			return true;
		}

		public int getSemType () {
			return 0;
		}

		public void setSemaphor (int type) {
		}

		@Override public String toString() {
		    StringBuilder result = new StringBuilder();
		    result.append(" Depot ");
		    return result.toString();
		  }

	}

	private class CityRail extends Rail {
		int renderIndex;
		/*check for free connection point:
		 * Every city can reach 3 points, (dx,0)(0,dy)(dx,dy)
		 * (dx,dy) have 2 variants
		 * We'll chose variant, check is it free and place rail*/
		public Rail connectTo ( Point p) {

			shift.set(p);
			boolean notDone = true;
			Point to = new Point(p);
			do {
				int variant = Country.randomGenerator.nextInt(4);

				if (variant < 2) renderIndex = 1; // set rail style
				else renderIndex = 0;

				if ((p.y-p.x) == 4) variant += 4; // Check side of country (rail rotation) and set dir selector
				System.out.println("Variant "+ variant + " at point" + p);

				rotation = NEXT_ENDROT[variant];
				to.add(NEXT_ENDX[variant] , NEXT_ENDY[variant]);
				if(!Country.links[ to.getIndex() ].isFree(NEXT_ENDDIR[variant])) {
					to.set(p);
					continue;
				}
				Switch sww = Country.links[ to.getIndex() ].getSw(NEXT_ENDDIR[variant]);
				if (variant<3 || variant>6) {
					swChange( sww , depot);
					newTrainPosition.dir = false;
					shift = to;
				} else {
					swChange( depot, sww);
					newTrainPosition.dir = true;
				}
				Country.links[to.getIndex()].addRail(NEXT_ENDDIR[variant], this, !newTrainPosition.dir);
				notDone = false;
			} while (notDone);
			cutTrees(false);
			return this;
		}

		public int getRailDir (Switch s) {
			if (renderIndex == 1)
				return 2;
			else
				return  (sw[0] == s)? 1 : 0 ;
		}

		public float getRailSize () {
			if (renderIndex == 1)
				return BASERAILSIZE;
			return BASERAILSIZE*1.6f;
		}

		public boolean checkColor (Vector3 col) {
			return col.equals(Country.CITY_COLORS[color]);
		}

		public boolean isCorrectPos(RailPosition p) {
			p.atDepot = false;
			//System.out.println (sw[0]+" " + sw[1] + " pos "+ p.pos);
			if( (p.pos >= getRailSize() && sw[(p.dir)?1:0].getClass() != Depot.class ) || (p.pos<=0 && sw[(p.dir)?0:1].getClass() != Depot.class ) ) return false;
			if (p.pos <=0 || p.pos >= getRailSize()) p.atDepot = true;
			return true;
		}

		public boolean getCoordinate(RailPosition pos) {
			railBusy = 5; // if somebody asked this - rail is busy

			if (pos.atDepot) return false; // keep outside screen
			if (renderIndex == 1) {
				RailStraight.calcCoord(shift, rotation, pos);
			} else {
				RailRound.calcCoord(shift, rotation, pos);
			}
			return true;
		}

		public void render (GL10 gl) {
			super.render(gl, renderIndex);
		}

	}

}
